package com.train.mgr.modules.biz.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.train.common.enums.AudioRuleEnum;
import com.train.mgr.modules.biz.dto.response.*;
import com.train.mgr.modules.biz.service.IAliQwenService;
import com.train.mgr.modules.biz.service.IAudioMetricRuleService;
import com.train.mgr.modules.biz.service.IFluencyService;
import com.train.mgr.modules.biz.utils.PromptTemplates;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 流畅度
 */
@Slf4j
@RequiredArgsConstructor
@Service("IFluencyService")
public class IFluencyServiceImpl implements IFluencyService {

    @Autowired
    private IAudioMetricRuleService iAudioMetricRuleService;

    @Autowired
    private IAliQwenService aliQwenService;

    /**
     * 流畅度得分 = 流利分 * 0.5 + 语速音量得分 * 0.5
     * @return
     */
    @Override
    public ScoreAndWenAnVo calFluencyScore(long audioDuration, AiAnalyzeResp aiAnalyzeResp){
        ScoreAndWenAnVo bean = new ScoreAndWenAnVo();
        double wpmAvgVoiced = aiAnalyzeResp.getWpm_avg_voiced(); //平均语速
        double loudnessDbfs = aiAnalyzeResp.getLoudness_dbfs(); //平均音量
        double loudnessDbfsStd = aiAnalyzeResp.getLoudness_dbfs_std(); //音量标准差
        Integer longPauseCount = aiAnalyzeResp.getLong_pause_count(); // 长停顿数
        AiAnalyzeResp.Disfluency disfluency = aiAnalyzeResp.getDisfluency();
        //流利分
        FluencyScoreVo fluency = this.getFluentScore(audioDuration,longPauseCount, disfluency);
        BigDecimal fluentScore = fluency.getFluencyScore();
        //语速音量得分
        SpeedAndVolumeVo speed = this.getSpeedAndVolume(wpmAvgVoiced,loudnessDbfs,loudnessDbfsStd);
        BigDecimal speedAndVolumeScore = speed.getSpeedAndVolumeScore();
        //流畅度得分
        BigDecimal fluencyScore =this.calcVolumeScore(fluentScore.floatValue(),speedAndVolumeScore.floatValue());
        //流畅度文案
        String fluencyWenAn= this.getFluencyQwenModel(fluency,speed,aiAnalyzeResp);
        log.info("流畅度得分:{}",fluencyScore);
        bean.setScore(fluencyScore);
        bean.setWenAn(fluencyWenAn);
        bean.setSpeedAndVolumeVo(speed);//语速音量得分对象
        bean.setWpmAvgVoiced(wpmAvgVoiced);//净语速
        return bean;
    }
//
//    /**
//     * 语速音量得分
//     * @param aiAnalyzeResp
//     * @return
//     */
//    @Override
//    public SpeedAndVolumeVo calSpeedAndVolume(AiAnalyzeResp aiAnalyzeResp){
//        log.info("语速音量得分---------------");
//        double wpmAvgVoiced = aiAnalyzeResp.getWpm_avg_voiced();//平均净语速
//        double loudnessDbfs = aiAnalyzeResp.getLoudness_dbfs(); //平均音量得分
//        double loudnessDbfsStd = aiAnalyzeResp.getLoudness_dbfs_std();//音量标准差得分
//        log.info("语速音量得分,wpmAvgVoiced:{},loudnessDbfs:{},loudnessDbfsStd:{}",wpmAvgVoiced,loudnessDbfs,loudnessDbfsStd);
//        //语速音量得分
//        return this.getSpeedAndVolume(wpmAvgVoiced,loudnessDbfs,loudnessDbfsStd);
//    }

    /**
     * 流畅度文案
     * @return
     */
    private String getFluencyQwenModel(FluencyScoreVo fluency,SpeedAndVolumeVo speed,AiAnalyzeResp aiAnalyzeResp){
        Map<String, List<String>> group = new LinkedHashMap<>();
        // 1. 汇总 FluencyScoreVo 里的 Desc（按 *LevelName 分组）
        putDesc(group, fluency.getRepeatScoreLevelName(), fluency.getRepeatScoreDesc());
        putDesc(group, fluency.getPauseScoreLevelName(), fluency.getPauseScoreDesc());
        putDesc(group, fluency.getCrutchScoreLevalName(), fluency.getCrutchScoreDesc());

        // 2. 汇总 SpeedAndVolumeVo 里的 Desc（按 *LevelName 分组）
        putDesc(group, speed.getLoudnessDbfsLavelName(), speed.getLoudnessDbfsDesc());
        putDesc(group, speed.getLoudnessDbfsStdLevelName(), speed.getLoudnessDbfsStdDesc());
        putDesc(group, speed.getWpmAvgVoicedLevelName(), speed.getWpmAvgVoicedDesc());
        putDesc(group, speed.getLongPauseLevelName(), speed.getLongPauseDesc());
        putDesc(group, speed.getCrutchWordLevelName(), speed.getCrutchWordDesc());

        // 3. 拼接结果：LevelName:desc1,desc2|LevelName2:desc3...
        String groupResult = group.entrySet().stream()
                .map(e -> e.getKey() + ":" + String.join(",", e.getValue()))
                .collect(Collectors.joining("；"));
        log.info("流畅度文案拼接prompt:{}",groupResult);
        //获取口头禅
        List<AiAnalyzeResp.FillersCounts> fillersHitsList = aiAnalyzeResp.getFillers_counts();
        String ktcMessage = "" ;
        String repairsMessage = "";
        if(fillersHitsList!=null && fillersHitsList.size()>0){
            // ktcMessage = fillersHitsList.stream().map(AiAnalyzeResp.FillersCounts::getFiller)      // 取 text
             //                               .filter(t -> t != null && !t.isEmpty())
             //                               .collect(Collectors.joining(","));
            ktcMessage = fillersHitsList.stream() .limit(4)                 // 前 4 条
                                                .map(AiAnalyzeResp.FillersCounts::getFiller)
                                                .collect(Collectors.joining(","));
        }

        //重复或修正
        List<AiAnalyzeResp.SelfRepairsHit>  selfRepairsHitsList = aiAnalyzeResp.getSelf_repairs_hits();
        if(selfRepairsHitsList !=null && selfRepairsHitsList.size() >0){
            repairsMessage = selfRepairsHitsList.stream().map(AiAnalyzeResp.SelfRepairsHit::getText)      // 取 text
                                                    .filter(t -> t != null && !t.isEmpty())
                                                    .collect(Collectors.joining(","));
        }

        String prompt = String.format(PromptTemplates.FLUENCY_SUMMARY,
                groupResult,
                repairsMessage,
                ktcMessage);
        log.info("【流畅度文案】提示词:{}",prompt);
        String message = aliQwenService.getQwenFeedBack(prompt);
       // log.info("【流畅度文案】阿里通义返回文案:{}",message);
        return message;
    }


    private void putDesc(Map<String, List<String>> map, String levelName, String desc) {
        if (levelName != null && desc != null) {
            map.computeIfAbsent(levelName, k -> new ArrayList<>()).add(desc);
        }
    }


    @Override
    public String getSpeedQwenModel(SpeedAndVolumeVo speedAndVolumeBean){
        String prompt = String.format(PromptTemplates.SPEED_VOLUME_SUMMARY,
                                        speedAndVolumeBean.getLoudnessDbfsLavelName(),
                                        speedAndVolumeBean.getLoudnessDbfsDesc(),
                                        speedAndVolumeBean.getLoudnessDbfsStdLevelName(),
                                        speedAndVolumeBean.getLoudnessDbfsStdDesc(),
                                        speedAndVolumeBean.getWpmAvgVoicedLevelName(),
                                        speedAndVolumeBean.getWpmAvgVoicedDesc());
        String filterString =  PromptTemplates.mergeByType(prompt);
        log.info("【语速音量】提示词:{}",filterString);
        String message = aliQwenService.getQwenFeedBack(filterString);
        //log.info("阿里通义返回【语速音量】得分文案:{}",message);
        return message;
    }


    /**
     * 流利分
     * @param audioDuration
     * @param longPauseCount
     * @param disfluency
     * @return
     */
    private FluencyScoreVo getFluentScore(long audioDuration, Integer longPauseCount, AiAnalyzeResp.Disfluency disfluency){
        FluencyScoreVo bean = new FluencyScoreVo();
        Integer fillers = disfluency.getFillers();//口头禅次数
        Integer repetition = disfluency.getRepetition();//重复词次数
        Integer selfRepairs = disfluency.getSelf_repairs();//自我修复次数

        //平均口头禅次数
        BigDecimal avgFillers =  this.avgDisfluencyMinuteCount(fillers,audioDuration);//单位转换(秒转换分钟)
        log.info("平均口头禅每分钟次数:{}", avgFillers);
        //重复词次数
        BigDecimal avgRepetition =  this.avgDisfluencyMinuteCount(repetition,audioDuration);//单位转换(秒转换分钟)
        log.info("重复词次数每分钟次数:{}", avgRepetition);
        //平均自我修复次数
        BigDecimal avgSelfRepairs =  this.avgDisfluencyMinuteCount(selfRepairs,audioDuration);//单位转换(秒转换分钟)
        log.info("平均自我修复次数:{}", avgSelfRepairs);
        //重复与修正分 = 直接重复+前缀重复+非填充重复+自我修正
        BigDecimal repeatScore = avgRepetition.add(avgSelfRepairs);
        log.info("repeatScore:{}",repeatScore);
        CalScoreResultVO repeatFixBean = iAudioMetricRuleService.calcByRule(AudioRuleEnum.repeat_fix.getCode(),repeatScore.doubleValue());
        log.info("重复与修正分:{}", repeatFixBean.getScore());
        bean.setRepeatScore(repeatFixBean.getScore());
        bean.setRepeatScoreDesc(repeatFixBean.getDescription());
        bean.setRepeatScoreLevelName(repeatFixBean.getLevelName());

        //平均长停顿次数
        BigDecimal avgLongPauseCount =  this.avgDisfluencyMinuteCount(longPauseCount,audioDuration);//单位转换(秒转换分钟)
        log.info("平均长停顿次数:{}", avgLongPauseCount);
        //口头禅分数
        //BigDecimal fillersScore = SpeechScoreUtil.crutchWordScore(avgFillers);
        CalScoreResultVO crutchWordBean = iAudioMetricRuleService.calcByRule(AudioRuleEnum.crutch_word.getCode(),avgFillers.doubleValue());
        log.info("口头禅分数:{}", JSONObject.toJSONString(crutchWordBean));
        BigDecimal crutchScore = crutchWordBean.getScore();
        bean.setCrutchScore(crutchScore);
        bean.setCrutchScoreDesc(crutchWordBean.getDescription());
        bean.setCrutchScoreLevalName(crutchWordBean.getLevelName());
        //停顿分
        CalScoreResultVO  longPauseBean = iAudioMetricRuleService.calcByRule(AudioRuleEnum.long_pause.getCode(),avgLongPauseCount.doubleValue());
        log.info("长停顿分分数:{}", JSONObject.toJSONString(longPauseBean));
        BigDecimal pauseScore = longPauseBean.getScore();
        bean.setPauseScore(pauseScore);
        bean.setPauseScoreDesc(longPauseBean.getDescription());
        bean.setPauseScoreLevelName(longPauseBean.getLevelName());

        //流利分=口头禅分*0.3 + 重复与修正分*0.2 + 长停顿分*0.4
        BigDecimal fluencyScore = this.calFluencyThreeScore(crutchScore,repeatFixBean.getScore(),pauseScore);
        log.info("流利分:{}", fluencyScore);
        bean.setFluencyScore(fluencyScore);
        log.info("FluencyScoreVo JSON:{}",JSONObject.toJSONString(bean));
        return bean;
    }


    /**
     * 语速音量检测
     * @param wpmAvgVoiced:净语速得分
     * @param loudnessDbfs: 平均音量得分
     * @param loudnessDbfsStd:  音量标准差
     * @param
     * @return
     */
    private SpeedAndVolumeVo getSpeedAndVolume(double wpmAvgVoiced, double loudnessDbfs, double loudnessDbfsStd){
        log.info("净语速字数/每分钟:{}",wpmAvgVoiced);
        SpeedAndVolumeVo bean = new SpeedAndVolumeVo();
        //平均音量得分
        CalScoreResultVO loudnessDbfsBean = iAudioMetricRuleService.calcByRule(AudioRuleEnum.avg_volume.getCode(),loudnessDbfs);
        log.info("平均音量得分:{}", loudnessDbfsBean.getScore());
        //音量标准差得分
        CalScoreResultVO loudnessDbfsStdBean = iAudioMetricRuleService.calcByRule(AudioRuleEnum.volume_std.getCode(),loudnessDbfsStd);
        log.info("音量标准差:{}", loudnessDbfsStdBean.getScore());
        //净语速得分(直接用AI接口)
        CalScoreResultVO wpmAvgVoicedBean = iAudioMetricRuleService.calcByRule(AudioRuleEnum.net_speed.getCode(),wpmAvgVoiced);
        log.info("净语速得分:{}", wpmAvgVoicedBean.getScore());
        //音量分
        BigDecimal volumeScore = this.calcVolumeScore(loudnessDbfsBean.getScore().doubleValue(),loudnessDbfsStdBean.getScore().doubleValue());
        //语速音量分 = 语速分 * 0.5 + 音量分 * 0.5
        BigDecimal speedAndVolumeScore = this.calcVolumeScore(wpmAvgVoicedBean.getScore().doubleValue(),volumeScore.doubleValue());
        log.info("音量分:{}",volumeScore);
        log.info("语速音量分:{}",speedAndVolumeScore);

        bean.setSpeedAndVolumeScore(speedAndVolumeScore);

        bean.setLoudnessDbfsDesc(loudnessDbfsBean.getDescription());
        bean.setLoudnessDbfsLavelName(loudnessDbfsBean.getLevelName());

        bean.setLoudnessDbfsStdDesc(loudnessDbfsStdBean.getDescription());
        bean.setLoudnessDbfsStdLevelName(loudnessDbfsStdBean.getLevelName());

        bean.setWpmAvgVoicedDesc(wpmAvgVoicedBean.getDescription());
        bean.setWpmAvgVoicedLevelName(wpmAvgVoicedBean.getLevelName());
        log.info("************************** 语速音量检测 Bean JSON:{} ", JSONObject.toJSONString(bean));
        return bean;
    }

    /**
     * 音量分 = 平均音量得分 * 0.5 + 音量标准差得分 * 0.5
     * /或者：
     * 语速音量得分 = 语速分 * 0.5 + 音量分 * 0.5
     * @param a  平均音量得分/语速分（0~100）
     * @param b  音量标准差得分/音量分（0~100）
     * @return 音量分，保留1位小数
     */
    public BigDecimal calcVolumeScore(double a,
                                      double b) {
        BigDecimal avg = BigDecimal.valueOf(a).setScale(3, RoundingMode.HALF_UP);
        BigDecimal std = BigDecimal.valueOf(b).setScale(3, RoundingMode.HALF_UP);

        BigDecimal volume = avg.multiply(new BigDecimal("0.5"))
                .add(std.multiply(new BigDecimal("0.5")));
        return volume.setScale(1, RoundingMode.HALF_UP);
    }

    /**
     * 不流利事件计分规则
     * 口头禅分*0.3 + 重复与修正分*0.2 + 长停顿分*0.4
     * @param crutchScore  口头禅分（0~100）
     * @param repeatScore  重复与修正分（0~100）
     * @param pauseScore   长停顿分（0~100）
     * @return 流利分，保留1位小数
     */
    private BigDecimal calFluencyThreeScore(BigDecimal crutchScore,
                                                  BigDecimal repeatScore,
                                                  BigDecimal pauseScore) {
        if (crutchScore == null) crutchScore = BigDecimal.ZERO;
        if (repeatScore == null) repeatScore = BigDecimal.ZERO;
        if (pauseScore == null) pauseScore = BigDecimal.ZERO;

        //log.info("**********calFluencyThreeScore*****crutchScore:{},repeatScore:{},pauseScore:{}",crutchScore,repeatScore,pauseScore);
        BigDecimal fluency = crutchScore.multiply(new BigDecimal("0.3"))
                            .add(repeatScore.multiply(new BigDecimal("0.2")))
                            .add(pauseScore.multiply(new BigDecimal("0.4")));
        BigDecimal fluencyScore = fluency.setScale(3, RoundingMode.HALF_UP);
        //log.info("*********calFluencyThreeScore******fluencyScore:{}",fluencyScore);
        return fluencyScore;
    }
//
//    public static void main(String[] args){
//        IFluencyServiceImpl aa = new IFluencyServiceImpl();
//        BigDecimal aaaa = aa.calFluencyThreeScore(new BigDecimal(0),new  BigDecimal(63),new BigDecimal(100));
//        System.out.println(aaaa);
//    }


    /**
     * 计算 平均每分钟次数
     * @param count 次数（Integer，允许null按0处理）
     * @param seconds 时长（秒，long类型）
     * @return 平均每分钟次数，保留1位小数；当seconds<=0时返回0
     */
    private BigDecimal avgDisfluencyMinuteCount(Integer count, long seconds) {
        int frequencyCount = count == null ? 0 : count;
        if (seconds <= 0) {
            return BigDecimal.ZERO;
        }
        // 先乘60再除，避免精度损失
        return BigDecimal.valueOf(frequencyCount * 60L)
                .divide(BigDecimal.valueOf(seconds), 3, RoundingMode.HALF_UP);
    }
}
